
package guoan.service.weixin;

import guoan.Exception.RestException;
import guoan.core.common.WebConfig;
import guoan.core.configuration.WeiXinCfgBean;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

@Service
public class OauthService {

    protected final Logger log = LoggerFactory.getLogger(getClass());
    private static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=#{appid}&secret=#{secret}&code=#{code}&grant_type=authorization_code";
    @Autowired
    private WeiXinCfgBean weiXinCfgBean;

    @Autowired
    private Gson gson;

    /**
     * @Title：createSSLClientDefault
     * @Description: @Title：createSSLClientDefault
     * @author Administrator
     * @date 2015年4月21日 下午5:38:57
     * @return
     */
    public CloseableHttpClient createSSLClientDefault(){
        try {
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(
                    null, new TrustStrategy() {
                        // 信任所有
                        @Override
                        public boolean isTrusted(X509Certificate[] chain,
                                String authType) throws CertificateException{
                            return true;
                        }
                    }).build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslContext);
            return HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        return HttpClients.createDefault();
    }

    public String findAccUrl(String code){
        // TODO Auto-generated method stub
        return ACCESS_TOKEN_URL.replace("#{appid}", weiXinCfgBean.getAppid())
                .replace("#{secret}", weiXinCfgBean.getAppscret())
                .replace("#{code}", code);
    }

    /**
     * @Title：oauth
     * @Description: 验证跳转
     * @author Administrator
     * @date 2015年4月22日 下午3:44:10
     * @param code
     * @param state
     * @param request
     * @return
     */
    public String oauth(String code, String state, HttpServletRequest request){
        // 获得openid
        CloseableHttpClient httpClient = createSSLClientDefault();
        HttpGet get = new HttpGet();
        try {
            String accurl = findAccUrl(code);
            log.debug("oauth2 begin accurl -> {}", accurl);

            get.setURI(new URI(accurl));
            CloseableHttpResponse response = httpClient.execute(get);
            try {
                HttpEntity entity = response.getEntity();
                log.debug("oauth2 begin entity -> {}", entity);

                if (entity != null) {
                    InputStream instream = entity.getContent();
                    log.debug("oauth2 begin instream -> {}", instream);

                    // Do not need the rest
                    final Type type = new TypeToken<Map<String, Object>>() {}
                            .getType();
                    final Map<Object, Object> map2 = gson.fromJson(
                            new InputStreamReader(instream, HTTP.UTF_8), type);
                    log.debug("oauth2 begin map2 -> {}", map2);
                    try {
                        String openid = String.valueOf(map2.get("openid"));
                         //openid = "123456";
                        log.debug("oauth2 begin openid -> {}", openid);

                        if (openid == null || openid.equals("null")) {
                            log.debug("oauth2 begin openid not find");
                            throw new RestException("请在微信中打开");
                        }

                        HttpSession session = request.getSession();
                        session.setAttribute(
                                WebConfig.SESSION_WEIXIN_OPENID_KEY, openid);
                        String rurl = weiXinCfgBean.findLinkValue(state);
                        if (rurl != null) {
                            return "redirect:" + rurl;
                        }
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        // 没有活动OPENID
                        log.debug("oauth2 begin openid not find");
                        return "/weixin/notOauth";
                    }
                }
            }
            finally {
                response.close();
            }
        } catch (URISyntaxException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return "/weixin/notOauth";
    }
}
